/**
 * STM32 SM2封装层
 * ProvideClass似于STM32硬件加密的接口
 */

#include "stm32f4xx_sm2.h"
#include "sm2_impl.h"
#include <string.h>

/* SM2上下文（全局） */
static SM2_Impl_Context sm2_ctx;
static uint8_t sm2_initialized = 0;
static uint8_t sm2_key_set = 0;

/**
 * @brief InitializeSM2Module
 */
HAL_StatusTypeDef SM2_Init(void)
{
    SM2_Impl_Init(&sm2_ctx);
    sm2_initialized = 1;
    sm2_key_set = 0;
    return HAL_OK;
}

/**
 * @brief SettingsSM2私钥
 */
HAL_StatusTypeDef SM2_SetKey(uint8_t* key, uint32_t key_len)
{
    if (!sm2_initialized) {
        return HAL_ERROR;
    }
    
    if (key == NULL || key_len < 32) {
        return HAL_ERROR;
    }
    
    /* Load私钥 */
    SM2_Impl_LoadKey(&sm2_ctx, key);
    
    /* Calculate公钥 */
    SM2_Impl_ComputePublicKey(&sm2_ctx);
    
    sm2_key_set = 1;
    return HAL_OK;
}

/**
 * @brief ExecuteSM2Command
 */
HAL_StatusTypeDef SM2_ProcessCommand(uint8_t cmd, 
                                     const uint8_t* input, 
                                     uint32_t input_len,
                                     uint8_t* output, 
                                     uint32_t* output_len)
{
    if (!sm2_initialized || !sm2_key_set) {
        return HAL_ERROR;
    }
    
    if (input == NULL || output == NULL || output_len == NULL) {
        return HAL_ERROR;
    }
    
    /* According toCommandExecute操作 */
    switch (cmd) {
        case SM2_CMD_SIGN:
            /* SM2签名: Input=哈希(32字节), Output=签名(64字节) */
            if (input_len != 32) {
                return HAL_ERROR;
            }
            SM2_Impl_Sign(&sm2_ctx, input, output);
            *output_len = 64;
            break;
            
        case SM2_CMD_VERIFY:
            /* SM2Verify: Input=公钥(64)+哈希(32)+签名(64), Output=Result(1) */
            if (input_len < 160) {
                return HAL_ERROR;
            }
            {
                const uint8_t* pubkey = input;
                const uint8_t* hash = input + 64;
                const uint8_t* signature = input + 96;
                int result = SM2_Impl_Verify(pubkey, hash, signature);
                output[0] = result ? 1 : 0;
                *output_len = 1;
            }
            break;
            
        default:
            return HAL_ERROR;
    }
    
    return HAL_OK;
}
